fix: restore the active top-level view across renderer reload#8265
Conversation
📝 WalkthroughWalkthroughPersisted UI state now includes the active top-level view, defaulting to 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/e2e/active-view-restart-restore.spec.ts (1)
101-109: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winGuard each cleanup step in the
finallyblock to prevent leaked resources.If
session.close(secondApp)throws,firstAppcleanup andsession.dispose()are skipped, potentially leaving Electron processes and temp directories lingering in CI. Wrapping each close in its own try/catch ensures all cleanup steps run.♻️ Proposed refactor
} finally { - if (secondApp) { - await session.close(secondApp) - } - if (firstApp) { - await session.close(firstApp) - } + for (const app of [secondApp, firstApp]) { + if (app) { + try { + await session.close(app) + } catch (error) { + console.error('Failed to close Electron app during cleanup:', error) + } + } + } await session.dispose() }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 964f2d1e-0f30-425b-8b09-8af5b56cb731
📒 Files selected for processing (7)
src/renderer/src/App.tsxsrc/renderer/src/lib/startup-ui-hydration.tssrc/renderer/src/store/slices/ui.test.tssrc/renderer/src/store/slices/ui.tssrc/shared/constants.tssrc/shared/types.tstests/e2e/active-view-restart-restore.spec.ts
b90b2ff to
2245593
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/renderer/src/lib/startup-ui-hydration.test.ts (1)
36-48: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAdd
activeViewcoverage to the fallback assertion. The fallback test only checks width/group/sort and sleeping-workspace flags, so the newactiveView: 'terminal'default isn’t exercised yet.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: eb5e3f58-e74e-49b2-8660-e8d6537b91ba
📒 Files selected for processing (10)
src/renderer/src/App.tsxsrc/renderer/src/components/automations/AutomationsPage.tsxsrc/renderer/src/hooks/useIpcEvents.tssrc/renderer/src/lib/startup-ui-hydration.test.tssrc/renderer/src/lib/startup-ui-hydration.tssrc/renderer/src/store/slices/ui.test.tssrc/renderer/src/store/slices/ui.tssrc/shared/constants.tssrc/shared/types.tstests/e2e/active-view-restart-restore.spec.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- tests/e2e/active-view-restart-restore.spec.ts
- src/shared/constants.ts
- src/shared/types.ts
- src/renderer/src/store/slices/ui.ts
- src/renderer/src/store/slices/ui.test.ts
2245593 to
f8c9f38
Compare
|
Thanks for the PR! |
* feat(file-explorer): confirm multi-select deletes with a single batch prompt (stablyai#7459) * feat(file-explorer): confirm multi-select deletes with a single batch prompt Deleting a multi-file selection on a remote host prompted once per file: requestDeleteAll awaited runDelete per root, and the remote-delete confirmation lived inside runDelete. Hoist the confirmation for batches — one 'Permanently delete {{count}} items?' dialog up front, then per-node deletes with skipConfirmation. Single-file and local (Trash) deletes are unchanged. Root filtering and the batch loop move to file-explorer-batch-deletion.ts with unit coverage. Fixes stablyai#7457 * fix(file-explorer): count the full selection in the batch delete prompt Address review: roots.length undercounts when a selected directory's children are also selected (could even read 'delete 1 items?'). Use the visible selection size instead. Also reword the zh strings so 项目 cannot read as 'project' in a file-delete flow. * review: skip batch delete confirm for unresolved-owner selections Narrow the batch-confirm gate to a resolvable remote route so an unresolved-owner multi-select no longer pops a destructive prompt for deletes that fail closed anyway — mirroring the single-delete path. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Tom de Bres <tomdebres@users.noreply.github.com> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * fix: pr-bug-scan validated finding from stablyai#6799 (stablyai#6839) * fix: address pr-bug-scan validated finding from stablyai#6799 Retain last-good resolved cwd on empty/error getCwd poll instead of committing null, so a transient lsof timeout no longer flips the followed worktree and resets the panel. * Add renderer startup timing diagnostics and fix stale terminal-cwd reten - Wraps each renderer startup hydration step (settings, repos, worktrees, session, SSH reconnect, etc.) with timing instrumentation gated behind ORCA_STARTUP_DIAGNOSTICS, wired through a new IPC channel (app:startupDiagnostic) so cold-start regressions can be measured. - Fixes the Checks panel's terminal-worktree tracking to clear the retained cwd when the active terminal itself changes, instead of only retaining across transient empty/error polls on the same terminal. --------- Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * Fix stale terminal panes after backgrounding by retrying deferred foreground recovery (stablyai#8198) * Fix stale terminal panes after backgrounding by retrying foreground reco - Foreground recovery was skipping the replay when resume landed mid-reconnect (socket typically dies after 60-80s backgrounded), leaving WKWebView panes blank until a manual tab switch. Recovery now returns a 'deferred' outcome and the session screen retries it once connState flips back to connected. - Fix a related race where a newly created tab's web-ready subscribe could be skipped if a lagging session-tab snapshot reset activeHandleRef before the subscribe fired; track the intended active handle separately. * Fix stale pending terminal handle outliving a failed create Clear pendingActiveTerminalHandleRef when terminal creation returns no handle, since web-ready subscribe logic gates on this ref being active and would otherwise see a stale value. * Simplify GitHub issue dialog workspace section to a status label (stablyai#8327) Remove the duplicated open/start workspace buttons and dropdown from GHEditSection now that the primary CTA lives in the issue header; show the attached workspace or "None yet" as plain metadata instead. * Remove host on mobile freeze the app (stablyai#8317) * Add host removal lifecycle safeguards and credential cleanup retry UI - Sequence host removal so metadata commits before the client socket closes, avoiding a stranded host when storage fails, and add a cancellable open-registry to stop races between host-client opens and closes/unmounts. - Queue AsyncStorage host-list mutations (rename/removal/lastConnected) to prevent concurrent writers from clobbering each other's changes. - Track keychain credential cleanups that fail or time out as durable pending intents, surfaced with a manual retry affordance in Settings. * Fix host removal error handling to reopen confirm dialog and alert user Previously a failed host removal silently closed the confirm dialog, leaving the host listed with no feedback and no easy retry path. Now the confirm modal reopens and an alert surfaces the failure so the user can retry. * test: reconcile settings tests with universal right-click paste and promoted worktree symlinks Merging main surfaced two semantic conflicts against this branch's tests: - stablyai#8322 exposed right-click paste on every platform, so the settings navigation metadata now indexes it even when only the terminal host is Windows. Update the stale assertion accordingly. - stablyai#8318 promoted APFS worktree shared paths by dropping the experimentalWorktreeSymlinks gate, so WorktreeSymlinksSection now always mounts inside RepositoryPane and reads window.api.fs. Stub a minimal renderer fs bridge in the pane test, matching the AppearancePane pattern. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai> * Fix Linux daemon shell fallback before PTY spawn (stablyai#8237) * fix: resolve daemon shell before spawning * fix(daemon): reconcile shell-ready barrier with the resolved fallback shell The adapter computes shellReadySupported from the preferred shell before spawn. When the daemon falls back (e.g. to /bin/sh), the session would queue startup commands for the full 15s ready-marker timeout and wrap multiline prompts in bracketed-paste markers the fallback shell cannot parse. Expose the spawned shell on SubprocessHandle and downgrade the barrier and paste wrapping in TerminalHost when the actual shell cannot emit the marker. Also apply the Unix shell fallback after the relay env scrub so a scrubbed SHELL cannot drop the corrected value, and cover the resolve- before-launch-config ordering, the no-shell throw, and candidate dedup with tests. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * release: v1.4.137-rc.0 * fix: strip trailing whitespace from xterm webgl patch (stablyai#8330) Blank context lines in the @xterm/addon-webgl patch had trailing spaces, which made git diff --check fail. Strip only that whitespace and refresh the pnpm patchedDependencies hash so the lockfile stays consistent. * skills: prefer agent-first worktree launch; avoid empty shell tabs (stablyai#7957) * skills: prefer agent-first worktree launch; avoid empty shell tabs Document Orca's first-terminal behavior so agents do not leave dead shell tabs: --agent runs in the first terminal (one tab), bare worktree create + terminal create leaves shell + agent (two tabs). Also: re-resolve live handles via terminal list after create, message one handle only, and prefer orchestration check --inject over terminal send for pure orchestration pings. Aligns with CLI docs (--agent launches the selected agent in the first terminal). * fix skill guidance for agent-first worktrees --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> * fix: use dynamic agent name in orca-cli worktree fallback command (stablyai#8341) Co-authored-by: Orca <help@stably.ai> * Distinguish failed PR file fetches from genuinely empty PRs and add a re (stablyai#8342) - gh file-fetch failures (rate limit, auth, unresolved remote) previously returned an empty array, which the Files tab rendered as "No files changed." — indistinguishable from a real empty PR - getPRFiles now returns null on failure; work-item-details surfaces this as filesUnavailable so GitHubItemDialog and PullRequestPage can show a retry action instead of a misleading empty state * release: v1.4.137-rc.1 * Fix F3: use known-tag predicate for explicit-turn decisions (stablyai#8331) * Fix F3: use known-tag predicate for explicit-turn decisions isHarnessInjectedUserTurnText matches any multi-word kebab tag, which is safe for non-destructive UI classification but wrong for state-transition decisions: a real prompt starting with a custom <my-element> paste looked like machinery in resolvePrompt/hasExplicitUserPrompt. Combined with the post-interrupt working-suppression in agent-hooks/server.ts, that left the agent visibly done after Ctrl+C. Switch both explicit-turn callsites to the known-tag isKnownHarnessInjectedUserTurnText predicate; known harness tags and Grok <user_query> behave unchanged. Co-authored-by: Orca <help@stably.ai> * Retire broad harness-tag matcher; unify on known-tag predicate The broad isHarnessInjectedUserTurnText had one remaining consumer: session title selection in session-scanner-primary-parsers.ts. Switch it to the known-tag predicate too — a real first turn that pastes a custom <my-element> now titles the session instead of being demoted to the meta (fallback) title. All observed first-turn machinery (system-reminder, caveat, command-name, task-notification, …) is already in the known list, so the only behavior change is that unknown, uncatalogued kebab tags stay user turns. Delete the now-unused broad predicate and fold its coverage into the known-predicate tests. Co-authored-by: Orca <help@stably.ai> * Fix bare <channel> tag being misclassified as harness machinery Only the attributed `<channel source=…>` form is emitted by the harness; a bare `<channel>` is legitimate user-pasted RSS/XML content. Remove 'channel' from the known-tag set (which matched any <channel ...>) and rely solely on the existing '<channel source=' prefix rule. --------- Co-authored-by: Orca <help@stably.ai> * fix(browser): make fill update rich text editors via execCommand (stablyai#6060) Rich editors reconcile browser editing transactions, while direct value/textContent writes can leave framework state stale. Classify explicit contenteditables through the requested agent-browser target, keep native fill and clear behavior for plain controls, and perform rich replacement or clear as one target-focused eval over stdin. Fail when the browser editing command is unavailable instead of presenting stale DOM state. Preserves input/change behavior and spinbutton handling for standard fields. Verified against Draft.js and ProseMirror model state plus focused-target clear regressions. Co-authored-by: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> * Assign GitHub issue types (Bug/Feature) via issue templates (stablyai#8346) Co-authored-by: Orca <help@stably.ai> * Use worktree path to resolve HEAD OID for merged PR lookups (stablyai#8349) - Pass the active `worktreePath` through IPC, RPC, and the GitHub client to ensure we fetch the correct HEAD OID when resolving merged PRs. - Validate incoming worktree paths against known repository worktrees in the main process to prevent forged path usage. - Escalate Checks Panel PR refresh requests from 'swr' to 'active' when a cached "no PR" miss predates when the panel became visible. * Update .npmrc rm exlcusions * Fix push-target resolution missing queue-discovered PRs (stablyai#8351) Include fallbackGitHubPR alongside linkedGitHubPR/linkedGitLabMR when determining whether a hosted review link resolves to a push target. Worktrees without persisted linkedPR metadata (e.g. child worktrees) were incorrectly blocked with "target unavailable" despite having a real matching upstream, since their PR was only known via the queue fallback. Also splits hasPositiveHostedReviewNumberLink to build on the resolvable subset so the two helpers can't drift. * fix(updater): force-exit stale process so update install can relaunch (stablyai#8328) Once quitAndInstall commits, Squirrel's ShipIt (and the Win/Linux installers) wait for the old app process to exit before replacing the bundle and relaunching. The quit path defers exit behind unbounded async teardown (daemon checkpoint RPCs at 30s each per session, SSH disconnects, watcher/emulator shutdown); if any of it wedges, the app looks closed but the process survives, ShipIt stalls, and the update never applies — 'Check for updates closes the app but never relaunches'. Arm a 20s unref'd exit watchdog at the exact install-commit point (where recovery is already forbidden) and disarm it on pre-commit recovery, so the old process is guaranteed to exit and the installer can relaunch. Fixes stablyai#4438 Co-authored-by: Orca <help@stably.ai> * fix(preflight): reject Windows paths from WSL agent lookup (stablyai#7994) * fix(preflight): reject Windows paths from WSL lookup WSL agent discovery previously treated path.win32 absolute results as valid guest paths, so a Windows absolute path like C:\spoof could be counted as a found agent. Only POSIX absolute paths are valid inside WSL. * docs(preflight): explain WSL path boundary * docs(preflight): correct WSL path rejection rationale Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * fix: host browser popups in an Orca origin-bar window instead of chrome-less child windows (stablyai#8343) * fix: host browser popups in an Orca origin-bar window instead of chrome-less child windows A guest-opened popup previously became a default Electron child window with no address bar, so users could not verify a popup's origin — a phishing surface flagged in the prod-release scan of stablyai#7392. The reverted stablyai#8332 tried gating on disposition, which is bypassable and breaks featureless window.open() OAuth flows. Instead, keep hosting popups in-app (preserving the shared session partition and live window.opener handle OAuth depends on) but build the child window ourselves via setWindowOpenHandler's createWindow callback: a BaseWindow with an Orca-controlled origin-bar WebContentsView on top and a content WebContentsView that adopts the pre-created popup WebContents. The bar shows only the destination origin (never path or query), updates on navigation, and flags plain http to remote hosts. Also pins secure webPreferences (contextIsolation, no nodeIntegration, sandbox, no webviewTag) on popup children via SAFE_POPUP_WINDOW_OPTIONS, attaches guest policies to popup contents directly (did-create-window does not fire for createWindow children), emits the existing opened-in-orca renderer notice, and closes popups with their opener guest. Co-authored-by: Orca <help@stably.ai> * fix: show page title in popup title bar instead of doubling the origin The native title bar and the origin bar both showed the origin, reading as a doubled header. Match Chrome popup behavior: title bar shows the page title (reset to origin on navigation so a stale title cannot outlive its origin); the origin bar below remains the unspoofable trust surface. Co-authored-by: Orca <help@stably.ai> * fix: elide the start of long popup origins so the registrable domain stays visible Adversarial review findings on the origin bar: - The bar right-ellipsized long hostnames, hiding exactly the part that matters: window.open('https://accounts.google.com.<...>.evil.com', '', 'width=360') rendered as 'https://accounts.google.com.signin.s…'. Clip from the left instead (rtl container + isolated ltr bdi so host and port keep normal character order), matching how Chrome elides. - Re-assert the origin on the popup's did-finish-load so a transiently dropped executeJavaScript write cannot leave a stale origin up. - Re-pin view layout on enter/leave-full-screen: verified at runtime that HTML5 fullscreen keeps the bar visible on macOS (resize fires); the explicit events make that hold on every platform. - Test hardening: fake WebContents now flips isDestroyed after 'destroyed' so the double-close guard is actually exercised. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai> * fix(mobile): don't orphan pairing tokens or leak rejections on host remove (stablyai#8317) (stablyai#8354) Prod-release-scan P1+P2 from v1.4.137-rc.1 mobile host-remove. P1: Host remove could orphan a SecureStore pairing token with no Settings retry when BOTH the durable pending-queue write failed AND the native delete rejected/stalled. recordCleanupIntent swallowed the queue-write failure, so the only recovery handle for the failed keychain delete was silently lost. Now scheduleHostCredentialCleanup keeps a session-scoped in-memory fallback handle when the durable write fails, so Settings still surfaces the pending cleanup and offers a retry; confirmNativeCleanup clears the fallback if the native delete later lands. removeHost stays non-blocking on the keychain (freeze fix intact). P2 (updateLastConnected): the fire-and-forget `void updateLastConnected(...)` call site threw on unreadable storage, producing an unhandled rejection. updateLastConnected now swallows unreadable-storage failures internally since it's a best-effort timestamp. P2 (soft-read): loadPendingHostCredentialCleanup now reports storageUnreadable instead of pretending the queue is empty, and Settings surfaces a "couldn't check cleanup status — retry to be safe" affordance rather than hiding the section when the durable queue can't be read. Tests: dual-fault fallback + no-clobber, storageUnreadable reporting, fallback self-heal on late delete success, and updateLastConnected non-throw. * Add Grok orchestration group routing (stablyai#8058) * docs: design Grok orchestration group * docs: plan Grok orchestration group implementation * fix: add Grok orchestration group * test(orchestration): accept Windows skill newlines * Fix @grok orchestration group matching and remove stale planning docs - Reuse the shared buildAgentNameRe matcher in groups.ts instead of a divergent local regex, so orchestration groups honor the same Windows launcher-suffix rule (grok.exe/.cmd/.bat/.ps1) as the rest of Orca's agent-title detection. - Add test coverage for real Grok OSC title shapes (spinner-collapsed, session titles) and Windows launcher-suffix titles. - Delete the now-completed design and implementation-plan docs for the Grok orchestration group work. --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> * fix(cleanup): reconcile late-settling removals against timeout results (stablyai#8348) * fix(cleanup): reconcile late removal results * fix(cleanup): report authoritative late removals * fix(cleanup): reconcile skipped ancestors on late child settlement Ancestor rows skipped past the removal deadline were reported as definitive failures even when the blocking child later succeeded or was still in flight. Track provisional vs. definitive skips, re-derive them as child settlements arrive mid-batch, requeue unblocked ancestors for retry, and add a "still removing" toast state so batch summaries stop contradicting rows that settle later. * Fix skipped-parent rows going stale after post-batch child settlement - Post-batch late child results (settling after the batch loop ends) previously ignored ancestor skip state, so a parent skipped for a since-resolved child kept a stale "could not be removed" failure instead of reclassifying and retrying. - Extracts reclassification logic into workspace-cleanup-skipped-ancestor-reclassification.ts, shared by the mid-batch and new post-batch paths. - Adds workspace-cleanup-post-batch-late-settlement.ts to reconcile ancestor skips and retry unblocked parents after late child settlement, serialized via a reconcile chain to avoid interleaving concurrent settlements. * fix(pi): keep status hooks off the Pi turn critical path (stablyai#8355) Pi awaits its extension event handlers, so an awaited loopback status post that stalls (Orca restarting / receiver unavailable) blocked the running Pi turn and disconnected it. Make post() fire-and-forget with a latest-only pending slot drained by a single active request and a 1s AbortController timeout, so a stalled receiver can never hold the turn. Also stop treating session_shutdown as turn completion: Pi emits it on reload/new/resume/fork while the PTY stays alive, so only agent_end proves done (real exit is cleared by PTY teardown). Split the generated handler registrations into agent-status-handler-source.ts. Co-authored-by: Orca <help@stably.ai> * Cli destructive suggest (stablyai#8352) * fix(cli): don't recover benign typos into destructive commands CLI did-you-mean ranked purely by Levenshtein, so `orca worktree move` sole-suggested `orca worktree remove` (distance 2) — an alias of the destructive `worktree rm`. Suggestions also flow into --json error.data.nextSteps, the agent recovery channel, so a blind retry could delete a clean worktree. Make destructiveness a declared property of the command instead of a verb heuristic: add `destructive?: true` to CommandSpec and mark the irreversible commands (worktree rm, environment rm, automations remove, project setup-delete, tab profile delete, cookie delete, storage local/session clear). The suggestion ranker excludes destructive candidates unless the input token is itself a near-miss (distance <=1) of a destructive verb, so `worktree remov` still recovers `rm`/`remove` while `worktree move` no longer does. The guard tracks the registry, so it also covers destructive verbs outside the delete family (e.g. kill). Fixes stablyai#6303 Co-authored-by: Orca <help@stably.ai> * fix(cli): use Array.at(-1) to satisfy oxlint prefer-at Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai> * Naming usage ui copy (stablyai#8357) * fix: work-item naming, usage % rounding, and terminal/delete copy Address prod-release-scan P2s: - stablyai#8238: recognize Bitbucket Server (/projects|users/.../repos/.../pull-requests/N) and Azure DevOps (/_git/REPO/pullrequest/N) PR URL shapes in work-item-reference, alongside Bitbucket Cloud; graceful fallback preserved. - stablyai#7574: getDisplayedUsagePercentage now rounds the used value before taking the `remaining` complement, so the compact status bar (raw usedPercent) and tooltip (pre-rounded clampUsedPercent) can no longer disagree by 1% at a .5 fraction. clampUsedPercent moves to the shared module as the single rounding source. - stablyai#7459: mixed remote+local batch delete confirm no longer claims the whole batch is a permanent "remote host" delete — it now states remote items are permanent while local items move to the Trash/Recycle Bin. - stablyai#8322: right-click-to-paste settings copy is platform-aware — "Control-click" on macOS, "Ctrl+right-click" on Windows/Linux — matching the ctrlKey gate. Localization catalog synced (also picks up pre-existing UsagePercentageDisplayChangeNotice drift). * Fix NaN% usage bar and label for non-finite provider values Non-finite usedPercent inputs (NaN/Infinity) propagated through Math.round/min/max into the CSS bar width (`NaN%`) and displayed copy. clampUsedPercent now short-circuits to 0 in that case, with a test covering the divergence from getDisplayedUsagePercentage for the 'remaining' case. * fix(runtime): explain full worktree id selectors (stablyai#7432) (stablyai#7892) * fix(runtime): explain full worktree id selectors (stablyai#7432) * Fix full worktree id selectors for bare repo ids and doc guidance - Reject bare repo-id selectors up front via a shared validator instead of relying on worktree-list scanning, so RPC callers no longer trigger an unnecessary rescan just to detect the mistake - Propagate the structured worktree_id_requires_full_path code through RPC error mapping so callers get a typed error, not just a message - Update orca-cli, orca-emulator, and orchestration skill docs to show the full `<repo-id>::<path>` id shape and stop implying a bare repo id is a valid worktree selector --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> * docs(computer-use): clarify get-app-state JSON tree field (stablyai#7788) * docs(computer-use): document get-app-state JSON response fields * docs(computer-use): correct get-app-state JSON guidance --------- Co-authored-by: 循安 林 <andylin2@fmt.com.tw> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> * Update README downloads badge * Fix Codex WSL project trust conflating case-distinct Linux paths (stablyai#8333) * Fix Codex WSL project trust conflating case-distinct Linux paths normalizeCodexProjectPathForLookup lowercased the entire Windows/UNC path, including the case-sensitive Linux portion under \\wsl$\<distro>. Two distinct WSL project dirs (.../Repo vs .../repo) collapsed onto one trust key, and the mirror dedupe (codex-config-mirror) inherited it. Preserve case for the Linux path after the case-insensitive \\wsl$\<distro> / \\wsl.localhost\<distro> share prefix; true Windows drive letters and normal UNC shares still case-fold as before. Co-authored-by: Orca <help@stably.ai> * Apply the same WSL case-fold fix to hook-trust key lookup normalizeHookTrustKeyForLookup had the identical latent bug: on a win32 host it lowercased the whole Windows-shaped path, folding the case-sensitive Linux tail of a \\wsl$\<distro> UNC hook path — contrary to its own comment that WSL sources stay case-sensitive. Extract foldWindowsCaseInsensitivePath (shared with the project-path normalizer): fold only the case-insensitive drive/\\wsl$ share prefix, preserve the Linux tail. Existing suffix (event:group:handler) is already lowercase, so behavior is unchanged there. Co-authored-by: Orca <help@stably.ai> * Fix Codex WSL trust revocation and hook-key case folding - Case-drifted or share-spelling-varied WSL revocations were being ignored on merge, letting stale "trusted" entries survive; fold revocation lookups fully so matching errs toward revoked. - Hook-trust key folding was gated on process.platform === 'win32', so WSL/SSH-remote hook sources weren't folded when Orca itself ran on macOS/Linux; fold by path shape instead, via the new shared foldWslUncPathCaseInsensitiveParts helper (also covers /mnt drvfs automounts and wsl$/wsl.localhost share aliasing). * Fix Codex WSL trust key case-folding regressions - Don't fold case-variant `/MNT` dirs as if they were the drvfs automount; only literal lowercase `/mnt/<drive>` folds. - Preserve an exact-cased trusted project entry in ~/.codex during runtime merge instead of letting a loosely-matched, case-drifted revocation clobber a user's re-granted trust on every mirror pass. - Minor cleanup: inline foldWindowsCaseInsensitivePath and hoist the repeated normalizeHookTrustKeyForLookup call in findTrustBlockRanges. * Refactor case-fold WSL trust test to assert real serializer output Extract path variables and assert against escapeTomlString(incomingPath) instead of a hardcoded escaped string literal, so the fixture can't silently drift from the actual TOML header serialization. --------- Co-authored-by: Orca <help@stably.ai> * fix(linux): stop Orca terminals from launching the GNOME Orca screen reader via bare `orca` (stablyai#8347) On Linux the CLI installs as orca-ide so it never shadows /usr/bin/orca (GNOME's screen reader), but agent-facing surfaces (orca-cli skill, dispatch preambles, CLI hints) all invoke bare `orca` — so on stock Ubuntu an agent inside an Orca terminal launched the screen reader, which started speaking (stablyai#7904). Fix: prepend a userData-scoped shim dir (bare `orca` -> bundled orca-ide launcher, or the stable AppImage) to the PATH of every packaged-Linux managed PTY, mirroring the existing dev-mode cli/bin prepend. The user's own shells — and their real screen reader command — stay untouched. Also flip the orca-cli skill probe to prefer orca-ide so agents outside Orca terminals never execute the screen reader. Fixes stablyai#7904 Co-authored-by: Orca <help@stably.ai> * release: v1.4.138-rc.0 * feat(ssh): support file transfers over system ssh (stablyai#7804) * feat(ssh): support file transfers over system ssh * fix(ssh): harden system file transfers * test(runtime): stub getRepo in headless mobile tab cwd test The mobile-session selector validator (getValidatedExplicitWorktreeIdSelector, from main) calls this.store?.getRepo to reject repo ids passed as worktree ids. The store stub only implemented getWorkspaceSession, so the guarded call threw 'getRepo is not a function' once main merged into this branch. Add a getRepo that returns null (wt-1 is a worktree, not a repo). Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * fix(codex): share the user's global AGENTS.md into the managed Codex runtime home (stablyai#7927) * fix(codex): share global AGENTS.md into managed runtime homes Orca launches Codex with a managed CODEX_HOME, so host and WSL sessions otherwise lose the user's global instructions. Share AGENTS.md through the existing ownership-aware link-or-copy path, with a narrow WSL launch sync that avoids copying unrelated resource directories. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(codex): copy global AGENTS.md into WSL runtime homes Symlinking across the \wsl.localhost 9P boundary stores a Windows UNC target the distro cannot resolve, so the global AGENTS.md silently would not load inside WSL when the host symlink succeeded. Copy it like the config mirror already does across the same boundary. Co-authored-by: Orca <help@stably.ai> * Fix WSL global-instruction sync to dereference symlinks and skip redunda - Copy AGENTS.md contents (not the symlink) into WSL runtime homes, since a host-side symlink is unusable inside the distro - Skip rewriting the fallback copy when source contents are unchanged, avoiding needless writes across the UNC boundary on every Codex launch - Handle non-regular-file sources and malformed/undeletable marker directories without blocking sync or stranding stale instructions --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * Resolve and require explicit push targets for linked reviews (stablyai#6159) Automatically resolve and require explicit push targets for linked GitHub PRs and GitLab MRs before allowing remote actions. This prevents operations like push or sync from targeting helper upstreams or falling back to default behaviors when the review target is unavailable. Also, recover missing push targets during metadata saves to heal existing linked PRs. * release: v1.4.138-rc.1 * fix(settings): make WSL skill commands pasteable (stablyai#7795) (stablyai#7881) * fix(settings): make WSL skill commands pasteable (stablyai#7795) * Fix WSL skill commands so PowerShell 7 pastes match PowerShell 5.1 argv - Encode the WSL login-shell script as base64 and decode/eval it inside the sh -c invocation, avoiding raw nested quotes at the paste boundary - Scope $PSNativeCommandArgumentPassing = 'Legacy' to the invocation so PS 5.1 and PS 7 both hand wsl.exe the same escaped argv - Extract powershell-native-argument.ts as the shared quoting module and reuse it from ssh-remote-powershell.ts * test(runtime): stub getRepo in mobile-tab startup cwd test Main's stablyai#7892 made listMobileSessionTabs validate selectors via this.store?.getRepo; the mock store here only defined getWorkspaceSession, so the merged CI build threw 'getRepo is not a function'. Return null (wt-1 is a worktree id, not a repo). Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * release: v1.4.138-rc.2 * Remove redundant line on PR evidence images Removed redundant line about committing PR evidence images. * fix: restore the active top-level view across renderer reload (stablyai#8265) Persist and safely restore the active top-level view on startup. Unknown, removed, legacy, or unavailable views fall back to the terminal, while cross-window UI sync cannot navigate the current window.\n\nCloses stablyai#8264 * fix(cli): preserve multiline arguments on Windows (stablyai#8374) * fix(cli): preserve multiline Windows arguments * test(cli): run Windows launcher regression in CI * fix(cli): support Windows Framework C# compiler * fix(orchestration): complete tasks on worker_done + coordinator UX fixes (stablyai#8030) * fix(orchestration): complete worker tasks and improve coordinator UX * Fix orchestration lifecycle sender resolution and peek/check compat hand - Lifecycle sends (worker_done/heartbeat) now use ORCA_TERMINAL_HANDLE verbatim, skipping the liveness probe and pane remint that could block delivery during restarts or mismatch stale-runtime assignee handles. - --peek now round-trips as {peek:true, unread:false} so older runtimes that strip unknown params degrade to non-destructive "all" instead of mark-read, with client-side filtering to restore peek semantics and a clear error when --peek --wait can't be honored. - Reject combined read-mode flags (--unread/--peek/--all) before calling the runtime. - Distinguish suppressed (already-consumed) lifecycle messages from ignored ones so send doesn't wake --wait waiters for stale heartbeats. - Fix task summary truncation to avoid splitting UTF-16 surrogate pairs and to not misreport whitespace normalization as truncation. * Add shared helper to abbreviate orchestration task specs for brief listi - Normalizes whitespace and caps spec length at 160 chars, flagging truncation separately from whitespace-only changes - Truncates on UTF-16 code point boundaries to avoid splitting surrogate pairs and emitting malformed strings * Add pane-key identity to worker_done/heartbeat reconciliation and server - Records the sender's pane key on messages and dispatch contexts so worker_done/heartbeat ownership can be verified by the remint-stable pane leaf instead of the terminal handle, which is reissued across restarts. - Rejects lifecycle messages from a genuinely foreign pane while still tolerating handle remints, tab break-outs, and older CLIs that lack pane identity. - Moves task-spec abbreviation server-side (orchestration.taskList --brief) so full specs no longer cross SSH/relay transports, with a client-side fallback for older runtimes; consolidates the shared abbreviation helper under src/shared. - Adds a stderr warning when a pre-peek runtime's --peek response hits the 100-row cap, since older unread messages may be missing. * Isolate ORCA_PANE_KEY in CLI test beforeEach to fix leaked senderPaneKey Co-authored-by: Orca <help@stably.ai> * Fix pane-key remint bypassing dispatch mutual-exclusion lock - Dispatch locking only matched on assignee_handle, so a reminted terminal handle (tab break-out) could open a second concurrent dispatch on the same pane. - Add leaf-UUID-based pane key comparison (parsePaneKey) as a secondary lock, falling back to exact handle match for legacy rows without pane keys. * Update orchestration skill docs for lifecycle authority and CLI flag add - Clarify that dispatch lifecycle is tied to taskId+dispatchId verified against the dispatched pane, not the terminal handle, since handles can be reminted after restart - Document new `check --peek`/`--all` and `task-list --brief` flags, with fallback guidance for older CLIs that reject them - Note that a valid worker_done auto-completes the task/dispatch, so workers shouldn't also call task-update manually --------- Co-authored-by: Orca <help@stably.ai> * ci(fork): skip upstream community tracker --------- Co-authored-by: Tom <debres.bot@gmail.com> Co-authored-by: Tom de Bres <tomdebres@users.noreply.github.com> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com> Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai> Co-authored-by: Vitus <zhzvitus@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ryushione <108252882+ryushione@users.noreply.github.com> Co-authored-by: Wolfie <wolfgangs2000@gmail.com> Co-authored-by: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com> Co-authored-by: BingZ <techzbing@gmail.com> Co-authored-by: Rod Boev <rod.boev@gmail.com> Co-authored-by: z116123123x <52649964+z116123123x@users.noreply.github.com> Co-authored-by: 循安 林 <andylin2@fmt.com.tw> Co-authored-by: gatsby74 <166927047+gatsby74@users.noreply.github.com> Co-authored-by: Robot. <topgrd@outlook.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Myungjoo Jang <wkdaudwn11@naver.com>
Summary / description
The active top-level view (Tasks, Automations, Mobile, Settings, Skills, Space, or the enabled Activity view) now survives a renderer reload or app relaunch instead of always resetting to the terminal.
activeViewnow uses Orca's existing persisted UI pipeline. Startup hydration restores a validated value once, while laterui:stateChangedbroadcasts continue syncing preferences without unexpectedly navigating an already-open window. Unknown values and a disabled experimental Activity view safely fall back to the terminal.Closes #8264
Evidence of fix
activeViewreached persisted main-process state, relaunches, and verifies the Tasks DOM is visible while the terminal DOM is hidden.main:1 passed (8.9s); the restore scenario itself completed in8.2s.151 passedacrossui.test.tsandstartup-ui-hydration.test.ts.ELI5
Orca remembered the details inside each screen, but it forgot which screen you were looking at. This change saves that screen name too. When Orca starts again, it checks that the saved name is still valid and opens that screen; background settings updates are not allowed to pull you away from the screen you are currently using.
Trade-offs / expected user regressions
No user regression is expected. The value uses the existing profile-level UI state, so the last desktop view written is the one restored on the next launch; a live window is never navigated by a cross-window/mobile sync. Like the surrounding UI preferences, writes are debounced by 150 ms, so a reload triggered almost immediately after navigation could still restore the prior view.
Screenshots
No visual change. The E2E test provides render-layer evidence for both the restored Tasks page and hidden terminal surface.
Testing
pnpm lint(focused Oxlint and the max-lines ratchet passed; the full repository lint suite was not run)pnpm typecheckpnpm test(focused suites passed: 151 tests)pnpm build(the E2E-mode Electron build passed; the full release build was not run)Commands run:
AI Review Report
Final review checked startup ordering, legacy/corrupt values, experimental-view gating, startup failure fallback, cross-window/mobile rebroadcast behavior, the debounced writer, and the full restart/render path. It identified that the contributor branch was behind
main; the branch was merged with currentmain, then all focused checks were repeated successfully.Cross-platform review covered macOS, Linux, and Windows. This change adds no shortcuts, shortcut labels, shell commands, platform-specific paths, or OS-specific Electron behavior. It uses the same typed IPC and persistence path on every platform. The SSH/remote use case is preserved because the restored view is app UI state and does not assume a local repository or filesystem path.
Security Audit
The persisted value is treated as untrusted: unknown, missing, legacy, or unavailable view values fall back to
terminal. The change adds no command execution, path handling, authentication, secrets, dependencies, or new IPC channel. It only extends the existing trusted partial UI-state payload with a validated navigation value. No security follow-up is needed.Notes
The original contributor PR was selected because it is the only linked candidate and already covered the important persistence and synchronization edge cases. It has been updated to current
mainand retained as the final PR so the contributor keeps authorship and discussion history.